package pikasial.graphique;

import pikasial.fs.ImageFilter;
import pikasial.images.ListeAlbums;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.io.IOException;

import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JSplitPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.xml.transform.TransformerException;

import org.xml.sax.SAXException;

import pikasial.Configuration;
import pikasial.Pikasial;
import pikasial.fs.Dossier;
import pikasial.fs.Fichier;
import pikasial.images.AlbumPhotos;
import pikasial.images.ImageContainer;
import pikasial.images.PikImage;
import pikasial.utils.GestionnaireCacheVignettes;
import pikasial.utils.MetaParser;

/**
 * Il s'agit de la fenêtre principale de l'application.
 * <p>
 * La fenetre principal de l'application, comprenant
 * <ul>
 * <li> la barre de menu (et ses écouteurs) </li>
 * <li> le navigateur de dossiers à gauche </li>
 * <li> le navigateur de photos à droite </li>
 * </ul>
 * @author ESIAL - Groupe 14
 */
@SuppressWarnings("serial")
public final class PikasialFrame extends JFrame implements WindowListener {

    /** La largeur par défaut de la fenêtre. */
    static final int LARGEUR_FENETRE = 960;
    /** La hauteur par défaut de la fenêtre. */
    static final int HAUTEUR_FENETRE = 700;
    /** Determine la place du séparateur. */
    static final int POSITION_SEPARATEUR = 250;
    /** Le navigateur de photos. */
    private ExplorateurVignettes navPhotos;
    /** Le panneau de gauche. */
    private PanneauGauche panneauGauche;
    private JMenu fichier,  edition,  affichage, aide;
    private JMenuItem cut,copy,paste,properties,fullscreen,visionneuse;

    /**
     * Crée une instance de la fenêtre et l'affiche.
     */
    public PikasialFrame() {
        super("Pikasial - Picture Manager");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setIconImage(new ImageIcon(getClass().getResource(pikasial.utils.PikasialConstantes.PIKASIAL_ICON_PATH)).getImage());
//        try {
//            UIManager.setLookAndFeel(
//                UIManager.getSystemLookAndFeelClassName());
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

        initMenus();
        initComponents();

        setSize(LARGEUR_FENETRE, HAUTEUR_FENETRE);
    }

    /**
     * Construit la barre de menu, et l'ajoute a la fenetre.
     */
    private void initMenus() {
        JMenuBar menu = new JMenuBar();

        /* Menu Fichier */
        fichier = new JMenu("Fichier");
        fichier.setMnemonic('f');

        JMenuItem nouvelAlbum = new JMenuItem("Nouvel album...");
        nouvelAlbum.setIcon(new ImageIcon(getClass().getResource(pikasial.utils.PikasialConstantes.ALBUM_NEW_16_ICON_PATH)));
        nouvelAlbum.setAccelerator(KeyStroke.getKeyStroke(
            KeyEvent.VK_N, InputEvent.CTRL_MASK));
        nouvelAlbum.addActionListener(new ActionListener() {

            public void actionPerformed(final ActionEvent ae) {
                nouvelAlbum();
            }
        });

        JMenuItem ajouterDossier =
            new JMenuItem("Ajouter un dossier à Pikasial...");
        ajouterDossier.setIcon(new ImageIcon(getClass().getResource(pikasial.utils.PikasialConstantes.OPENED_FOLDER_16_ICON_PATH)));
        ajouterDossier.setAccelerator(KeyStroke.getKeyStroke(
            KeyEvent.VK_O, InputEvent.CTRL_MASK));
        ajouterDossier.addActionListener(new ActionListener() {

            public void actionPerformed(final ActionEvent ae) {
                importDossier();
            }
        });

        JMenuItem ajouterFichier =
            new JMenuItem("Ajouter un fichier à Pikasial...");
        ajouterFichier.setIcon(new ImageIcon(getClass().getResource(pikasial.utils.PikasialConstantes.IMAGE_16_ICON_PATH)));
        ajouterFichier.addActionListener(new ActionListener() {

            public void actionPerformed(final ActionEvent ae) {
                importFichier();
            }
        });

        JMenuItem quitter = new JMenuItem("Quitter");
        quitter.setAccelerator(KeyStroke.getKeyStroke(
            KeyEvent.VK_Q, InputEvent.CTRL_MASK));
        quitter.setIcon(new ImageIcon(getClass().getResource(pikasial.utils.PikasialConstantes.CLOSE_16_ICON_PATH)));
        quitter.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent ae) {
                quitter();
            }
        });

        fichier.add(nouvelAlbum);
        fichier.addSeparator();
        fichier.add(ajouterDossier);
        fichier.add(ajouterFichier);
        fichier.addSeparator();
        fichier.add(quitter);

        /* Menu Edition */
        edition = new JMenu("Edition");
        edition.setMnemonic('e');
        JMenuItem selectAll = new JMenuItem("Tout sélectionner");
        selectAll.setAccelerator(KeyStroke.getKeyStroke(
            KeyEvent.VK_A, InputEvent.CTRL_MASK));
        selectAll.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                navPhotos.selectAll();
            }
        });

        JMenuItem invertSelection = new JMenuItem("Inverser la sélection");
        invertSelection.setAccelerator(KeyStroke.getKeyStroke(
            KeyEvent.VK_I, InputEvent.CTRL_MASK));
        invertSelection.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                navPhotos.inverserSelection();
            }
        });

        JMenuItem effacerSelection = new JMenuItem("Effacer la sélection");
        effacerSelection.setAccelerator(KeyStroke.getKeyStroke(
            KeyEvent.VK_D, InputEvent.CTRL_MASK));
        effacerSelection.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                navPhotos.effacerSelection();
            }
        });

        cut = new JMenuItem("Couper",new ImageIcon(getClass()
        		.getResource(pikasial.utils.PikasialConstantes.CUT_16_ICON_PATH)));
        cut.setMnemonic('x');
        cut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_MASK));
        cut.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent ae) {
        		if (!navPhotos.isSelectionEmpty())
        			PressePapier.getInstance().couper(navPhotos.getSelectedVignettes(),navPhotos.getAlbum());
        	}
        });
        copy = new JMenuItem("Copier",new ImageIcon(getClass()
        		.getResource(pikasial.utils.PikasialConstantes.COPY_16_ICON_PATH)));
        copy.setMnemonic('c');
        copy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,KeyEvent.CTRL_MASK));
        copy.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent ae) {
        		if (!navPhotos.isSelectionEmpty())
        			PressePapier.getInstance().copier(navPhotos.getSelectedVignettes());
        	}
        });
        paste = new JMenuItem("Coller",new ImageIcon(getClass()
        		.getResource(pikasial.utils.PikasialConstantes.PASTE_16_ICON_PATH)));
        paste.setMnemonic('v');
        paste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V,KeyEvent.CTRL_MASK));
        paste.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent ae) {
        		if (!PressePapier.getInstance().isEmpty()) {
        			PikImage[] imgs = PressePapier.getInstance().coller();
        			for (PikImage pik : imgs) {
        				navPhotos.getAlbum().addImage(pik);
        			}
        			navPhotos.getListModel().synchroniserAvecAlbum();
        		}
        	}
        });

        properties = new JMenuItem("Propriétés");
        properties.setIcon(new ImageIcon(getClass()
        		.getResource(pikasial.utils.PikasialConstantes.PROPERTIES_16_ICON_PATH)));
        properties.setMnemonic('p');
        properties.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P,KeyEvent.CTRL_MASK));
        properties.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                PikImage p = (PikImage) navPhotos.getSelectedVignette();
                new ProprietesImageDialog(p);
            }
        });
        edition.add(selectAll);
        edition.add(invertSelection);
        edition.add(effacerSelection);
        edition.addSeparator();
        edition.add(cut);
        edition.add(copy);
        edition.add(paste);
        edition.addSeparator();
        edition.add(properties);

        /* Menu Affichage */
        affichage = new JMenu("Affichage");
        affichage.setMnemonic('a');
        JMenuItem diaporama = new JMenuItem("Afficher un diaporama", 'd');
        diaporama.setIcon(new ImageIcon(getClass().getResource(pikasial.utils.PikasialConstantes.SLIDESHOW_16_ICON_PATH)));
        diaporama.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent ae) {
                ImageContainer ic = navPhotos.getAlbum();
                if (ic == null || ic.isEmpty()) {
                    JOptionPane.showMessageDialog(PikasialFrame.this, "L'album est vide !", "Erreur !", JOptionPane.ERROR_MESSAGE);
                } else {
                    PikasialFrame.this.afficherDiaporama(ic);
                }
            }
        });
        fullscreen = new JMenuItem("Afficher en plein écran",'f');
        fullscreen.setIcon(new ImageIcon(getClass().getResource(pikasial.utils.PikasialConstantes.FULLSCREEN_16_ICON_PATH)));
        fullscreen.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent ae) {
        		if (!navPhotos.isSelectionEmpty()) {
            		Diaporama d = new Diaporama(navPhotos.getAlbum());
            		d.afficher();
            		d.afficherImage(navPhotos.getSelectedVignette());
            	}
        	}
        });
        visionneuse = new JMenuItem("Afficher dans la visionneuse",'h');
        visionneuse.setIcon(new ImageIcon(getClass().getResource(pikasial.utils.PikasialConstantes.ALBUM_16_ICON_PATH)));
        visionneuse.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent ae) {
        		if (!navPhotos.isSelectionEmpty())
        			VisionneuseImage.getInstance().afficherImage(navPhotos.getSelectedVignette());
        	}
        });
        affichage.add(diaporama);
        affichage.add(fullscreen);
        affichage.add(visionneuse);
//        /* Menu Outils */
//        outils = new JMenu("Outils");
//        outils.setMnemonic('o');

        /* Menu Aide */
        aide = new JMenu("Aide");
        aide.setMnemonic('d');

        JMenuItem help = new JMenuItem("Aide");
        help.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.getKeyText(KeyEvent.VK_F1)));
        help.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                try{
                    Runtime r = Runtime.getRuntime();
                    String[] com = {"evince", getClass().getResource("/divers/aide.pdf").getPath()};
                    System.out.println(com[0]);
                    r.exec(com);
                    }
                 catch (IOException err){
                        JOptionPane.showMessageDialog(null,"Erreur lors de l'ouverture de l'aide","aide",JOptionPane.ERROR_MESSAGE);
                    }
                }
        });
        aide.add(help);

        JMenuItem aProposDe = new JMenuItem("A propos");
        aProposDe.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                (new AProposDialog(PikasialFrame.this)).afficher();
            }
        });
        aide.add(aProposDe);

        /* Ajoute les menus à la barre */
        menu.add(fichier);
        menu.add(edition);
        menu.add(affichage);
//        menu.add(outils);
        menu.add(aide);

        /* Ajoute la barre de menu à la fenetre */
        setJMenuBar(menu);
    }

    /**
     * Initialise les differents composants de la fenetre et
     * les ajoute au panneau principal.
     */
    private void initComponents() {
        addWindowListener(this);
        panneauGauche = new PanneauGauche();
        navPhotos = new ExplorateurVignettes();
        //navPhotos.afficherAlbum(new AlbumPhotos(""));

        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
            panneauGauche, navPhotos);
        splitPane.setOneTouchExpandable(true);
        splitPane.setDividerLocation(POSITION_SEPARATEUR);

        getContentPane().add(splitPane);
    }

    /**
     * Permet d'accèder au panneau contenant les photos.
     * @return l'instance du navigateur de photos
     * @see pikasial.graphique.NavigateurPhotos
     */
    public ExplorateurVignettes getExplorateurVignettes() {
        return navPhotos;
    }

    /**
     * Permet d'accèder au panneau de gauche.
     *
     * @return le panneau de gauche.
     */
    public PanneauGauche getPanneauGauche() {
        return panneauGauche;
    }

    /**
     * Permet à l'utilisateur de choisir un fichier sur un disque local
     * pour l'importer dans Pikasial.
     * <p>
     * Seules des images peuvent être importées dans Pikasial.
     * @see pikasial.graphique.ImageFilter
     * @see pikasial.fs.PikasialFS#add(Fichier, boolean)
     */
    public void importFichier() {
        JFileChooser fc = new JFileChooser();

        fc.addChoosableFileFilter(new ImageFilter());
        fc.setAcceptAllFileFilterUsed(false);

        int ret = fc.showOpenDialog(this);

        if (ret == JFileChooser.APPROVE_OPTION) {
            File file = new File(fc.getSelectedFile().getPath());
            Pikasial.getPikasialFS().add(new Fichier(file), true);
            System.out.println("Fichier " + file.getPath() + " importé par l'utilisateur.");
        } else {
            System.out.println("Import fichier annulé par l'utilisateur.");
        }

    }

    /**
     * Permet à l'utilisateur de choisir un dossier sur un disque local
     * pour l'importer dans Pikasial.
     * <p>
     * Seules les images contenues dans le dossier sont importées,
     * ainsi que les sous-dossiers contenant eux-mêmes des images
     * @see pikasial.fs.PikasialFS#add(Dossier, boolean)
     */
    public void importDossier() {
        JFileChooser fc = new JFileChooser();
        fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int ret = fc.showOpenDialog(this);

        if (ret == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            Dossier d = new Dossier(file);
            pikasial.fs.PikasialFS.getInstance().add(d, false);

            System.out.println("Dossier " + file.getPath() + " importé par l'utilisateur.");
        } else {
            System.out.println("Import dossier annulé par l'utilisateur.");
        }
    }

    /**
     * Permet à l'utilisateur de créer un nouvel album.
     */
    void nouvelAlbum() {
        String nomAlbum = (String) JOptionPane.showInputDialog(this,
            "Nom de l'album :", "Nouvel album",
            JOptionPane.QUESTION_MESSAGE);
        if (nomAlbum != null) {
        	if (ListeAlbums.getInstance().containsAlbum(nomAlbum)) {
        		JOptionPane.showMessageDialog(this,
        				"Ce nom est déjà utilisé !",
        				"Erreur",
        				JOptionPane.ERROR_MESSAGE);
        	} else if (nomAlbum.length() > 0) {
        		AlbumPhotos ap = new AlbumPhotos(nomAlbum);
        		ListeAlbums.getInstance().ajouterAlbum(ap);
        	}
        }
    }

    void afficherDiaporama(ImageContainer ic) {
        Diaporama diaporama = new Diaporama(ic);
        diaporama.afficher();
        diaporama.diaporama();
    }

    void quitter() {
        try {
            GestionnaireCacheVignettes.getInstance().
                saveThumbnailsToDisk(getExplorateurVignettes().getAlbum());
            org.w3c.dom.Document doc = MetaParser.getInstance().createAlbumsDOMTree();
            MetaParser.getInstance().saveAlbumList(doc);
            Configuration.getInstance().saveConfigToDisk();
            System.exit(0);
        } catch (IOException e) {
            JOptionPane.showMessageDialog(this, e.getMessage(), "Erreur !",
                JOptionPane.ERROR_MESSAGE);
        } catch (TransformerException te) {
        }
    }

    public void windowActivated(WindowEvent arg0) {}

    public void windowClosed(WindowEvent arg0) {
    }

    public void windowClosing(WindowEvent arg0) {
        quitter();
    }

    public void windowDeactivated(WindowEvent arg0) {
    }

    public void windowDeiconified(WindowEvent arg0) {
    }

    public void windowIconified(WindowEvent arg0) {
    }

    public void windowOpened(WindowEvent arg0) {
        try {
            MetaParser.getInstance().parseAlbumsFile();
        } catch (IOException e) {
            JOptionPane.showMessageDialog(this, "Erreur pendant le chargement de vos albums !" + e.getMessage(), "Erreur !", JOptionPane.ERROR_MESSAGE);
        } catch (SAXException e) {
            JOptionPane.showMessageDialog(this,
                "Erreur pendant la lecture du fichier contenant les albums (albums.xml) !\n" +
                e.getMessage(), "Erreur !", JOptionPane.ERROR_MESSAGE);
            e.printStackTrace();
        }
    }
}


